package com.itheima.leetcode.od.c.logicalsimulation;

import java.util.Arrays;
import java.util.Scanner;

/**
 * <h3>采样过滤</h3>
 */
public class SamplingAndFiltering {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        int[] tmp = Arrays.stream(sc.nextLine().split(" ")).mapToInt(Integer::parseInt).toArray();

        m = tmp[0];
        t = tmp[1];
        p = tmp[2];

        s = Arrays.stream(sc.nextLine().split(" ")).mapToInt(Integer::parseInt).toArray();

        System.out.println(getResult());
    }

    // 故障确认周期数m, 故障次数门限t, 故障恢复周期数p
    static int m, t, p;
    // 一段周期的采样数据列表
    static int[] s;

    static int[] status;

    static final int NORMAL = 1; // 正常数据的状态
    static final int FAULT = 2; // 错误数据的状态
    static final int ABORT = 3; // 丢弃的状态
    static final int RECOVERY_NORMAL = 4; // 故障恢复检查期间的正常数据的状态
    static final int RECOVERY_FAULT = 5; // 故障恢复检查期间的错误数据的状态

    public static int getResult() {
        // 记录每个采样数据的状态
        status = new int[s.length];

        // M个周期可以当成滑窗，l是滑窗的左边界
        int l = 0;
        // 滑窗内错误数据的个数
        int window_fault_count = 0;

        // 滑窗右边界纳入新数据
        for (int r = 0; r < s.length; r++) {

            // 如果滑窗长度超过了m，那么滑窗的左边界需要右移
            if (r - l + 1 > m) {
                // 如果右移前的，滑窗左边界对于的数据状态是FAULT，则右移后的滑窗内错误数据个数-1
                if (status[l++] == FAULT) {
                    window_fault_count--;
                }
            }

            // 检查数据状态
            if (check_normal(r)) {
                // 如果数据正常，则标记status[r]为正常状态
                status[r] = NORMAL;
            } else {
                // 如果数据异常，则需要检查当前数据前面一个数据的状态
                if (r < 1 || status[r - 1] == ABORT) {
                    // 如果当前数据前面一个数据的状态是丢弃的，则当前数据没有代替值，也需要被丢弃
                    status[r] = ABORT;
                    // 一旦出现丢弃数据，则滑窗中断，此时需要重置滑窗
                    window_fault_count = 0;
                    l = r + 1;
                } else {
                    // 如果当前数据前面一个数据的状态不是丢弃状态，那么滑窗内错误数据个数+1
                    if (++window_fault_count < t) {
                        // 如果滑窗内错误数据个数没有超过阈值t，那么可以用前面一个数据代替
                        status[r] = FAULT;
                        s[r] = s[r - 1];
                    } else {
                        // 如果滑窗内错误数据个数超过了阈值t，那么 r 位置就是故障开始的位置
                        // 此时 r 位置数据需要被丢弃，此时滑窗中断，需要重置滑窗
                        status[r] = ABORT;
                        window_fault_count = 0;

                        // i 位置就是 故障恢复检查期开始位置
                        int i = r + 1;

                        // 故障恢复检查期内连续正确数据个数
                        int recovery_correct_count = 0;

                        while (i < s.length) {
                            if (check_recovery(i)) {
                                recovery_correct_count++;
                                status[i] = RECOVERY_NORMAL;

                                // 当故障恢复期间，连续正确数据个数达到p，则故障解除
                                if (recovery_correct_count == p) {
                                    break;
                                }
                            } else {
                                recovery_correct_count = 0;
                                status[i] = RECOVERY_FAULT;
                            }

                            i++;
                        }

                        // i 位置是故障解除的位置，则下一次，我们应该从 i+1 位置开始重新判断，即滑窗的左、右边界都要更新为i+1
                        if (i < s.length) {
                            l = i + 1;
                            r = i; // 这里r没有等于 i+1，是因为for循环会给r++
                        }
                    }
                }
            }
        }

        // 最后只需要找到 status 数组中最长的连续NORMAL和FAULT即可
        int maxLen = 0;
        int len = 0;

        for (int sta : status) {
            if (sta == NORMAL || sta == FAULT) {
                len++;
            } else {
                maxLen = Math.max(maxLen, len);
                len = 0;
            }
        }

        return Math.max(maxLen, len);
    }

    // 正常期间检查
    public static boolean check_normal(int i) {
        if (s[i] <= 0) {
            return false; // S[i] <= 0，即为错误值
        }

        // 和前面采样数据比较的前提条件是：前面的采样数据必须是正常状态，或者正常期错误状态
        if (i >= 1 && (status[i - 1] == NORMAL || status[i - 1] == FAULT)) {
            if (s[i] < s[i - 1]) {
                return false; // S[i] < S[i-1]，即为错误值
            }
            if (s[i] - s[i - 1] >= 10) {
                return false; // S[i] - S[i-1] >= 10，即为错误值
            }
        }

        return true; // 其它情况为正常值
    }

    // 故障恢复期检查
    public static boolean check_recovery(int i) {
        if (s[i] <= 0) {
            return false; // S[i] <= 0，即为错误值
        }

        // 和前面采样数据比较的前提条件是：前面的采样数据不能时丢弃状态，以及恢复期错误状态
        if (i >= 1 && status[i - 1] != ABORT && status[i - 1] != RECOVERY_FAULT) {
            if (s[i] < s[i - 1]) {
                return false; // S[i] < S[i-1]，即为错误值
            }
            if (s[i] - s[i - 1] >= 10) {
                return false; // S[i] - S[i-1] >= 10，即为错误值
            }
        }

        return true; // 其它情况为正常值
    }
}